home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------*/
- /* LHarc Add Command */
- /* This is part of LHarc UNIX Archiver Driver */
- /* */
- /* Copyright(C) MCMLXXXIX Yooichi.Tagawa */
- /* */
- /* V0.00 Original 1988.05.23 Y.Tagawa */
- /* V1.00 Fixed 1989.09.22 Y.Tagawa */
- /* V1.02 Bug fix 1990.01.19 Y.Tagawa */
- /* V0.03 LHa for UNIX 1991.12.05 M.Oki */
- /*----------------------------------------------------------------------*/
-
- #include "lharc.h"
-
- extern int encode_lzhuf ();
- extern int encode_stored_crc ();
-
- static char new_archive_name_buffer [ FILENAME_LENGTH ];
- static char *new_archive_name;
- FILE *temporary_fp = NULL;
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
-
-
-
- static void
- add_one (fp, nafp, hdr)
- FILE *fp, *nafp;
- LzHeader *hdr;
- {
- long header_pos, next_pos, org_pos, data_pos;
- long v_original_size, v_packed_size;
-
- reading_filename = hdr->name;
- writting_filename = temporary_name;
-
- if (!fp && generic_format) /* [generic] doesn't need directory info. */
- return;
- header_pos = ftell (nafp);
- write_header (nafp, hdr); /* DUMMY */
-
- if (hdr->original_size == 0) /* empty file or directory */
- return; /* previous write_header is not DUMMY. (^_^) */
-
- org_pos = ftell (fp);
- data_pos = ftell (nafp);
-
- hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
- &v_original_size, &v_packed_size, hdr->name, hdr->method);
-
- if (v_packed_size < v_original_size)
- {
- next_pos = ftell (nafp);
- }
- else
- { /* retry by stored method */
- fseek (fp, org_pos, SEEK_SET);
- fseek (nafp, data_pos, SEEK_SET);
- hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
- &v_original_size, &v_packed_size);
- fflush (nafp);
- next_pos = ftell (nafp);
- #ifndef NOFTRUNCATE
- ftruncate (fileno (nafp), next_pos);
- #endif
- bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
- }
- hdr->original_size = v_original_size;
- hdr->packed_size = v_packed_size;
- fseek (nafp, header_pos, SEEK_SET);
- write_header (nafp, hdr);
- fseek (nafp, next_pos, SEEK_SET);
- }
-
-
- FILE *
- append_it (name, oafp, nafp)
- char *name;
- FILE *oafp, *nafp;
- {
- LzHeader ahdr, hdr;
- FILE *fp;
- long old_header;
- int cmp;
- int filec;
- char **filev;
- int i;
- struct stat stbuf;
- boolean directory;
-
- if (stat (name, &stbuf) < 0)
- {
- error ("cannot access", name); /* See cleaning_files, Why? */
- return oafp;
- }
-
- directory = is_directory (&stbuf);
-
- init_header (name, &stbuf, &hdr);
-
- if (!directory && !noexec)
- fp = xfopen (name, READ_BINARY);
- else
- fp = NULL;
-
- while (oafp)
- {
- old_header = ftell (oafp);
- if (!get_header (oafp, &ahdr))
- {
- fclose (oafp);
- oafp = NULL;
- break;
- }
- else
- {
- cmp = STRING_COMPARE (ahdr.name, hdr.name);
- if (cmp < 0)
- { /* SKIP */
- /* copy old to new */
- if (!noexec)
- {
- fseek (oafp, old_header, SEEK_SET);
- copy_old_one (oafp, nafp, &ahdr);
- }
- else
- fseek (oafp, ahdr.packed_size, SEEK_CUR);
- }
- else if (cmp == 0)
- { /* REPLACE */
- /* drop old archive's */
- fseek (oafp, ahdr.packed_size, SEEK_CUR);
- break;
- }
- else /* cmp > 0, INSERT */
- {
- fseek (oafp, old_header, SEEK_SET);
- break;
- }
- }
- }
-
- if (update_if_newer)
- {
- if (!oafp || /* not in archive */
- cmp > 0 || /* // */
- ahdr.unix_last_modified_stamp < /* newer than archive's */
- hdr.unix_last_modified_stamp)
- {
- if (noexec)
- printf ("ADD %s\n", name);
- else
- add_one (fp, nafp, &hdr);
- }
- else /* cmp == 0 */
- { /* copy old to new */
- if (!noexec)
- {
- fseek (oafp, old_header, SEEK_SET);
- copy_old_one (oafp, nafp, &ahdr);
- }
- }
- }
- else
- {
- if (!oafp || cmp > 0) /* not in archive or dropped */
- {
- if (noexec)
- printf ("ADD %s\n", name);
- else
- add_one (fp, nafp, &hdr);
- }
- else /* cmp == 0 */ /* replace */
- {
- if (noexec)
- printf ("REPLACE\n");
- else
- add_one (fp, nafp, &hdr);
- }
- }
-
- if (!directory)
- {
- if (!noexec)
- fclose (fp);
- }
- else
- { /* recurcive call */
- if (find_files (name, &filec, &filev))
- {
- for (i = 0; i < filec; i ++)
- oafp = append_it (filev[i], oafp, nafp);
- free_files (filec, filev);
- }
- }
- return oafp;
- }
-
- static void
- find_update_files (oafp)
- FILE *oafp; /* old archive */
- {
- char name[FILENAME_LENGTH];
- struct string_pool sp;
- LzHeader hdr;
- long pos;
- struct stat stbuf;
- int len;
-
- pos = ftell (oafp);
-
- init_sp (&sp);
- while (get_header (oafp, &hdr))
- {
- if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
- {
- if (stat (hdr.name, &stbuf) >= 0) /* exist ? */
- add_sp (&sp, hdr.name, strlen (hdr.name) + 1);
- }
- else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
- {
- strcpy (name, hdr.name);
- len = strlen (name);
- if (len > 0 && name[len - 1] == '/')
- name[--len] = '\0'; /* strip tail '/' */
- if (stat (name, &stbuf) >= 0) /* exist ? */
- add_sp (&sp, name, len+1);
- }
- fseek (oafp, hdr.packed_size, SEEK_CUR);
- }
-
- fseek (oafp, pos, SEEK_SET);
-
- finish_sp (&sp, &cmd_filec, &cmd_filev);
- }
-
- static void
- delete (oafp, nafp)
- FILE *oafp, *nafp;
- {
- LzHeader ahdr;
- long old_header_pos;
-
- old_header_pos = ftell (oafp);
- while (get_header (oafp, &ahdr))
- {
- if (need_file (ahdr.name))
- { /* skip */
- fseek (oafp, ahdr.packed_size, SEEK_CUR);
- if (noexec)
- printf ("DELETE %s\n", ahdr.name);
- else if (verbose)
- printf ("Delete %s\n", ahdr.name);
- }
- else
- { /* copy */
- if (noexec)
- {
- fseek (oafp, ahdr.packed_size, SEEK_CUR);
- }
- else
- {
- fseek (oafp, old_header_pos, SEEK_SET);
- copy_old_one (oafp, nafp, &ahdr);
- }
- }
- old_header_pos = ftell (oafp);
- }
- return;
- }
-
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
- static FILE *
- build_temporary_file ()
- {
- int old_umask;
- FILE *afp;
-
- build_temporary_name ();
- signal (SIGINT, interrupt);
- signal (SIGHUP, interrupt);
-
- old_umask = umask (077);
- afp = xfopen (temporary_name, WRITE_BINARY);
- remove_temporary_at_error = TRUE;
- temporary_fp = afp;
- umask (old_umask);
-
- return afp;
- }
-
- static void
- build_backup_file ()
- {
-
- build_backup_name (backup_archive_name, archive_name);
- if (!noexec)
- {
- signal (SIGINT, SIG_IGN);
- signal (SIGHUP, SIG_IGN);
- if (rename (archive_name, backup_archive_name) < 0)
- fatal_error (archive_name);
- recover_archive_when_interrupt = TRUE;
- signal (SIGINT, interrupt);
- signal (SIGHUP, interrupt);
- }
- }
-
- static void
- report_archive_name_if_different ()
- {
- if (!quiet && new_archive_name == new_archive_name_buffer)
- {
- /* warning at old archive is SFX */
- printf ("New archive file is \"%s\"\n", new_archive_name);
- }
- }
-
- #ifdef TMP_FILENAME_TEMPLATE
- void
- temporary_to_new_archive_file (new_archive_size)
- long new_archive_size;
- {
- FILE *oafp, *nafp;
-
- oafp = xfopen (temporary_name, READ_BINARY);
- if (!strcmp(new_archive_name, "-"))
- {
- nafp = stdout;
- writting_filename = "starndard output";
- }
- else
- {
- nafp = xfopen (new_archive_name, WRITE_BINARY);
- writting_filename = archive_name;
- }
- reading_filename = temporary_name;
- copyfile (oafp, nafp, new_archive_size, 0);
- if (nafp != stdout) fclose (nafp);
- fclose (oafp);
-
- recover_archive_when_interrupt = FALSE;
- unlink (temporary_name);
-
- remove_temporary_at_error = FALSE;
- }
- #else
- temporary_to_new_archive_file (new_archive_size)
- long new_archive_size;
- {
- char *p;
- p = (char *)rindex(new_archive_name,'/');
- p = p ? p+1 : new_archive_name;
- unlink ( new_archive_name );
- if ( rename ( temporary_name , p )<0 ) {
- fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
- exit(1);
- }
- }
- #endif
-
- static void
- set_archive_file_mode ()
- {
- int umask_value;
- struct stat stbuf;
-
- if (archive_file_gid < 0)
- {
- umask (umask_value = umask (0));
- archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
- if (stat (".", &stbuf) >= 0)
- archive_file_gid = stbuf.st_gid;
- }
- if (archive_file_gid >= 0)
- chown (new_archive_name, getuid (), archive_file_gid);
-
- chmod (new_archive_name, archive_file_mode);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* REMOVE FILE/DIRECTORY */
- /*----------------------------------------------------------------------*/
-
- static void remove_files ();
-
- static void
- remove_one (name)
- char *name;
- {
- struct stat stbuf;
- int filec;
- char **filev;
-
- if (stat (name, &stbuf) < 0)
- {
- warning ("Cannot access", name);
- }
- else if (is_directory (&stbuf))
- {
- if (find_files (name, &filec, &filev))
- {
- remove_files (filec, filev);
- free_files (filec, filev);
- }
- else
- warning ("Cannot open directory", name);
-
- if (noexec)
- printf ("REMOVE DIRECTORY %s\n", name);
- else if (rmdir (name) < 0)
- warning ("Cannot remove directory", name);
- else if (verbose)
- printf ("Removed %s.\n", name);
- }
- else if (is_regularfile (&stbuf))
- {
- if (noexec)
- printf ("REMOVE FILE %s.\n", name);
- else if (unlink (name) < 0)
- warning ("Cannot remove", name);
- else if (verbose)
- printf ("Removed %s.\n", name);
- }
- else
- {
- error ("Cannot remove (not a file or directory)", name);
- }
- }
-
- static void
- remove_files (filec, filev)
- int filec;
- char **filev;
- {
- int i;
-
- for (i = 0; i < filec; i++)
- remove_one (filev[i]);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
- void
- cmd_add ()
- {
- LzHeader ahdr;
- FILE *oafp, *nafp;
- int i;
- long old_header;
- boolean old_archive_exist;
- long new_archive_size;
-
- /* exit if no operation */
- if (!update_if_newer && cmd_filec == 0)
- {
- error ("No files given in argument, do nothing.", "");
- return;
- }
-
- /* open old archive if exist */
- if ((oafp = open_old_archive ()) == NULL)
- old_archive_exist = FALSE;
- else
- old_archive_exist = TRUE;
-
- if (update_if_newer && cmd_filec == 0 && !oafp)
- fatal_error (archive_name); /* exit if cannot execute automatic update */
- errno = 0;
-
- if (new_archive && old_archive_exist)
- {
- fclose (oafp);
- oafp = NULL;
- }
-
- if (oafp && archive_is_msdos_sfx1 (archive_name))
- {
- skip_msdos_sfx1_code (oafp);
- build_standard_archive_name (new_archive_name_buffer, archive_name);
- new_archive_name = new_archive_name_buffer;
- }
- else
- {
- new_archive_name = archive_name;
- }
-
- /* build temporary file */
- if (!noexec)
- nafp = build_temporary_file ();
-
- /* find needed files when automatic update */
- if (update_if_newer && cmd_filec == 0)
- find_update_files (oafp);
-
- /* build new archive file */
- /* cleaning arguments */
- cleaning_files (&cmd_filec, &cmd_filev);
- if (cmd_filec == 0)
- {
- if (oafp)
- fclose (oafp);
- if (!noexec)
- fclose (nafp);
- return;
- }
-
- for (i = 0; i < cmd_filec; i ++)
- oafp = append_it (cmd_filev[i], oafp, nafp);
- if (oafp)
- {
- old_header = ftell (oafp);
- while (get_header (oafp, &ahdr))
- {
- if (noexec)
- fseek (oafp, ahdr.packed_size, SEEK_CUR);
- else
- {
- fseek (oafp, old_header, SEEK_SET);
- copy_old_one (oafp, nafp, &ahdr);
- }
- old_header = ftell (oafp);
- }
- fclose (oafp);
- }
- if (!noexec)
- {
- write_archive_tail (nafp);
- new_archive_size = ftell (nafp);
- fclose (nafp);
- }
-
- /* build backup archive file */
- if (old_archive_exist)
- build_backup_file ();
-
- report_archive_name_if_different ();
-
- /* copy temporary file to new archive file */
- if (!noexec && (!strcmp(new_archive_name, "-") ||
- rename (temporary_name, new_archive_name) < 0))
- temporary_to_new_archive_file (new_archive_size);
-
- /* set new archive file mode/group */
- set_archive_file_mode ();
-
- /* remove archived files */
- if (delete_after_append)
- remove_files (cmd_filec, cmd_filev);
-
- return;
- }
-
-
- void
- cmd_delete ()
- {
- FILE *oafp, *nafp;
- long new_archive_size;
-
- /* open old archive if exist */
- if ((oafp = open_old_archive ()) == NULL)
- fatal_error (archive_name);
- errno = 0;
-
- /* exit if no operation */
- if (cmd_filec == 0)
- {
- fclose (oafp);
- warning ("No files given in argument, do nothing.", "");
- return;
- }
-
- if (archive_is_msdos_sfx1 (archive_name))
- {
- skip_msdos_sfx1_code (oafp);
- build_standard_archive_name (new_archive_name_buffer, archive_name);
- new_archive_name = new_archive_name_buffer;
- }
- else
- {
- new_archive_name = archive_name;
- }
-
- /* build temporary file */
- if (!noexec)
- nafp = build_temporary_file ();
-
- /* build new archive file */
- delete (oafp, nafp);
- fclose (oafp);
-
- if (!noexec)
- {
- write_archive_tail (nafp);
- new_archive_size = ftell (nafp);
- fclose (nafp);
- }
-
- /* build backup archive file */
- build_backup_file ();
-
- report_archive_name_if_different ();
-
- /* copy temporary file to new archive file */
- if (!noexec && rename (temporary_name, new_archive_name) < 0)
- temporary_to_new_archive_file (new_archive_size);
-
- /* set new archive file mode/group */
- set_archive_file_mode ();
-
- return;
- }
-